from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
from pypinyin import pinyin, Style
import pyinotify
import psycopg2
import logging
import daemon
import shutil
import time
import re 
import os


class MaxLinesHandler(logging.Handler):
    
    def __init__(self, filename,max_lines=None):
        super().__init__()
        self.max_lines = max_lines
        self.filename = filename
    
    def emit(self, record):
        with open(self.filename, 'a') as file_handle:
            file_handle.write(self.format(record) + '\n')
        with open(self.filename, 'r') as file_handle:
            lines = file_handle.readlines()
        if self.max_lines is not None:
            if len(lines) > self.max_lines:
                with open(self.filename, 'w') as file_handle:
                    file_handle.writelines(lines[-self.max_lines:])


class SameLogFilter(logging.Filter):
    def __init__(self):
        self.last_log = None

    def filter(self, record):
        current_log = record.getMessage()
        if current_log != self.last_log:
            self.last_log = current_log
            return True
        return False


def setup_logger(name,max_lines,log_file):
    # 创建日志记录器
    logger = logging.getLogger(name)
    logger.setLevel(logging.DEBUG)
    # 创建,添加自定义的 Handler文件处理程序
    file_handler = MaxLinesHandler(filename=log_file,max_lines=max_lines)
    file_handler.setLevel(logging.INFO)
    # 创建,添加自定义过滤器
    log_filter = SameLogFilter()
    file_handler.addFilter(log_filter)
    # 创建日志格式器
    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
    file_handler.setFormatter(formatter)
    # 添加处理程序到日志记录器
    logger.addHandler(file_handler)
    return logger


def select_table(cargs,tile):
    query = f"""
        SELECT distinct dt_sy.qhmc
        FROM china_tile
        JOIN dt_sy 
        on st_intersects(china_tile.geom,dt_sy.shape)
        WHERE china_tile.tile = '{tile}' 
        """
    connection = psycopg2.connect(**cargs)
    connection.autocommit = True
    connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
    cursor = connection.cursor()
    try:
        cursor.execute(query)
        connection.commit()
        data = cursor.fetchall()
    except Exception as e:
        connection.rollback()
    cursor.close()
    connection.close() 
    return data


def tile_2_qhdmqhmc(cargs,tile):
    query = f"""
        SELECT distinct qhdm,qhmc
        FROM qh_tile
        WHERE tile = '{tile}' 
        and CHAR_LENGTH(qhdm) = 2;
        """
    while True:
        try:
            connection = psycopg2.connect(**cargs)
            connection.autocommit = True
            cursor = connection.cursor()
            cursor.execute(query)
            connection.commit()
            data = cursor.fetchall()
            cursor.close()
            connection.close() 
            # connection.rollback()
            break
        except:
            time.sleep(60*5)
    return data


def hanzi_to_pinyin_capitalize(text):
    """
    将汉字转换为拼音，每个字的首字母大写
    """
    text = text.replace('省','').replace('市','').replace('自治区','')
    text = text.replace('维吾尔族','').replace('藏族','').replace('壮族','').replace('回族','')
    if text == "陕西":
        pinyin_list = [['shaan'],['xi']]
    else:
        pinyin_list = pinyin(text, style=Style.NORMAL)
    capitalized_pinyin = ''.join([word[0].capitalize() for word in pinyin_list])
    return capitalized_pinyin


def copy_zip_file(sourcedir,targetdir,cargs,logger):
    zipnamere = "^S2[A|B]_MSIL1C_.*_N.*_R.*_T.*_.*.zip$"
    for root,_,filenames in os.walk(sourcedir,topdown=True):
        for filename in filenames:
            if not re.match(zipnamere,filename): continue
            tile = filename.split('_')[5][1:]
            date = filename.split('_')[2][:6]
            data = tile_2_qhdmqhmc(cargs,tile)
            for qhdm,qhmc in data:
                result = hanzi_to_pinyin_capitalize(qhmc)
                sydir = os.path.join(targetdir,f"{qhdm}{result}",date)
                if not os.path.exists(sydir): os.makedirs(sydir)
                tpath = os.path.join(sydir,filename)
                if os.path.exists(tpath): continue
                spath = os.path.join(root,filename)
                try:
                    shutil.copyfile(spath, tpath)
                    logger.info(f"Success:From {spath} to {tpath}")
                except OSError as e:
                    logger.info(f"Failure:From {spath} to {tpath}")
    return


# 定义寧件处理
class EventHandler(pyinotify.ProcessEvent):
    zipnamere = "^S2[A|B]_MSIL1C_.*_N.*_R.*_T.*_.*.zip$"
    
    def __init__(self,cargs,folder,logger):
        # 调用父类的构造函数进行初始化
        super().__init__()
        self.cargs = cargs
        self.folder = folder
        self.logger = logger

    def process_IN_CREATE(self,event):
        if re.match(self.zipnamere,event.name):
            tile = event.name.split('_')[5][1:]
            date = event.name.split('_')[2][:6]
            data = select_table(self.cargs,tile)
            for qhmc, in data:
                sydir = os.path.join(self.folder,qhmc,date)
                if not os.path.exists(sydir): os.makedirs(sydir)
                tpath = os.path.join(sydir,event.name)
                if os.path.exists(tpath): continue
                spath = os.path.join(event.path,event.name)
                try:
                    os.link(spath, tpath)
                    self.logger.info(f"Hard link created successfully {tpath}")
                except OSError as e:
                    self.logger.info(f"Failed to create hard link: {e}")
        return

    def process_IN_DELETE(self,event):
        if re.match(self.zipnamere,event.name):
            tile = event.name.split('_')[5][1:]
            date = event.name.split('_')[2][:6]
            data = select_table(self.cargs,tile)
            for qhmc, in data:
                sydir = os.path.join(self.folder,qhmc,date)
                tpath = os.path.join(sydir,event.name)
                if not os.path.exists(tpath): continue
                tinode = os.stat(tpath).st_ino
                spath = os.path.join(event.path,event.name)
                sinode = os.stat(spath).st_ino
                if tinode == sinode: os.remove(tpath)
                self.logger.info(f"Delete hard link : {tpath}")
        return

    def process_IN_MOVED_TO(self,event):
        if re.match(self.zipnamere,event.name):
            tile = event.name.split('_')[5][1:]
            date = event.name.split('_')[2][:6]
            data = select_table(self.cargs,tile)
            for qhmc, in data:
                sydir = os.path.join(self.folder,qhmc,date)
                if not os.path.exists(sydir): os.makedirs(sydir)
                tpath = os.path.join(sydir,event.name)
                if os.path.exists(tpath): continue
                spath = os.path.join(event.path,event.name)
                try:
                    os.link(spath, tpath)
                    self.logger.info(f"Hard link created successfully {tpath}")
                except OSError as e:
                    prinself.logger.infot(f"Failed to create hard link: {e}")
        return


def main_(watch_dir,cargs,folder,logger):
    # 创建inotify.实例
    logger.info('启动数据同步')
    watch_manager = pyinotify.WatchManager()
    # 注册草件处理程序
    handler = EventHandler(cargs,folder,logger)
    # 创建Notifier对象
    notifier = pyinotify.Notifier(watch_manager,handler)
    mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | \
        pyinotify.IN_MOVED_TO | pyinotify.IN_MOVED_FROM | \
        pyinotify.IN_MODIFY # pyinotify.ALL_EVENTS
    watch_manager.add_watch(watch_dir,mask,rec=True) 
    notifier.loop()
    return


def main():
    cargs = {
        "database":"henan_rsanalysis",
        "user":"postgres",
        "password":"postgresql",
        "host":"192.168.1.71", 
        "port":"5432"}
    logger = setup_logger('本地数据同步',500,r'/data/fengyy/logfile/本地数据同步.log')
    sourcedir = r"/data/ygjsb/Backup/MonthSentinelZip"
    targetdir = r"/data/ygjsb/data/ProvinceMonthZip"
    while True:
        copy_zip_file(sourcedir,targetdir,cargs,logger)
        print("休眠1分钟")
        time.sleep(60*60)
    return

 
def run_daemon():
    work_dir= r'/data/fengyy/project/CopernicusSentinel2Level1C'
    with daemon.DaemonContext(
        working_directory=work_dir,
        stdout=open(r"/data/fengyy/logfile/FileSystemMonitoringout.log","w"),
        stderr=open(r"/data/fengyy/logfile/FileSystemMonitoringerr.log","w")
        ):
        main()


if __name__ == "__main__":
    run_daemon()
    # main()
